<!DOCTYPE html>
<html lang="en">
	<head>
		<title>three.js webgl - buffer geometry constructed from geometry</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		<style>
			body {
				color: #ffffff;
				background-color: #000000;
				margin: 0px;
				overflow: hidden;
			}
			#info {
				position: absolute;
				top: 0px;
				width: 100%;
				padding: 5px;
				font-family: Monospace;
				font-size: 13px;
				text-align: center;
			}
			a {
				color: #0080ff;
			}
		</style>
		<script type="text/javascript" src="../build/three.js"></script>
		<script type="text/javascript" src="js/Detector.js"></script>
		<script type="text/javascript" src="js/libs/stats.min.js"></script>
		<script type="text/javascript" src="js/controls/TrackballControls.js"></script>
	</head>
	<body>
		<div id="info"><a href="http://threejs.org" target="_blank">three.js</a> webgl - buffer geometry constructed from geometry - (<a target="_blank" href="http://callum.com">author</a>)</div>
		<script>

		if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

		var camera, scene, renderer, controls, stats;

		init();
		animate();

		function init() {

			renderer = new THREE.WebGLRenderer( {
				antialias: true
			} );
			renderer.setPixelRatio( window.devicePixelRatio );
			renderer.setSize( window.innerWidth, window.innerHeight );

			document.body.appendChild( renderer.domElement );

			scene = new THREE.Scene();

			camera = new THREE.PerspectiveCamera( 45.0, window.innerWidth / window.innerHeight, 100, 1500.0 );
			camera.position.z = 480.0;

			scene.add( new THREE.AmbientLight( 0x444444 ) );

			var light1 = new THREE.DirectionalLight( 0x999999, 0.1 );
			light1.position.set( 1, 1, 1 );
			scene.add( light1 );

			var light2 = new THREE.DirectionalLight( 0x999999, 1.5 );
			light2.position.set( 0, -1, 0 );
			scene.add( light2 );

			controls = new THREE.TrackballControls( camera, renderer.domElement );
			controls.minDistance = 100.0;
			controls.maxDistance = 800.0;
			controls.dynamicDampingFactor = 0.1;

			stats = new Stats();
			document.body.appendChild( stats.dom );

			window.addEventListener( 'resize', onWindowResize, false );

			createScene();

		}

		function createGeometry() {

			var heartShape = new THREE.Shape(); // From http://blog.burlock.org/html5/130-paths
			var x = 0, y = 0;

			heartShape.moveTo( x + 25, y + 25 );
			heartShape.bezierCurveTo( x + 25, y + 25, x + 20, y, x, y );
			heartShape.bezierCurveTo( x - 30, y, x - 30, y + 35, x - 30, y + 35 );
			heartShape.bezierCurveTo( x - 30, y + 55, x - 10, y + 77, x + 25, y + 95 );
			heartShape.bezierCurveTo( x + 60, y + 77, x + 80, y + 55, x + 80, y + 35 );
			heartShape.bezierCurveTo( x + 80, y + 35, x + 80, y, x + 50, y );
			heartShape.bezierCurveTo( x + 35, y, x + 25, y + 25, x + 25, y + 25 );

			var extrudeSettings = {
				amount: 16,
				bevelEnabled: true,
				bevelSegments: 1,
				steps: 2,
				bevelSize: 1,
				bevelThickness: 1
			};

			var geometry = new THREE.ExtrudeGeometry( heartShape, extrudeSettings );
			geometry.rotateX( Math.PI );
			geometry.scale( 0.4, 0.4, 0.4 );

			return geometry;

		}

		function createScene() {

			var bufferGeometry = new THREE.BufferGeometry();

			var radius = 125;
			var count = 80;

			var positions = [];
			var normals = [];
			var colors = [];

			var spherical = new THREE.Spherical();
			var vector = new THREE.Vector3();

			for ( var i = 1, l = count; i <= l; i ++ ) {

				var phi = Math.acos( -1 + ( 2 * i ) / l );
				var theta = Math.sqrt( l * Math.PI ) * phi;

				spherical.set( radius, phi, theta );
				vector.setFromSpherical( spherical );

				var geometry = createGeometry();

				geometry.lookAt( vector );
				geometry.translate( vector.x, vector.y, vector.z );

				var color = new THREE.Color( 0xffffff );
				color.setHSL( ( i / l ), 1.0, 0.7 );

				geometry.faces.forEach( function ( face, index ) {

					positions.push( geometry.vertices[ face.a ].x );
					positions.push( geometry.vertices[ face.a ].y );
					positions.push( geometry.vertices[ face.a ].z );
					positions.push( geometry.vertices[ face.b ].x );
					positions.push( geometry.vertices[ face.b ].y );
					positions.push( geometry.vertices[ face.b ].z );
					positions.push( geometry.vertices[ face.c ].x );
					positions.push( geometry.vertices[ face.c ].y );
					positions.push( geometry.vertices[ face.c ].z );

					normals.push( face.normal.x );
					normals.push( face.normal.y );
					normals.push( face.normal.z );
					normals.push( face.normal.x );
					normals.push( face.normal.y );
					normals.push( face.normal.z );
					normals.push( face.normal.x );
					normals.push( face.normal.y );
					normals.push( face.normal.z );

					colors.push( color.r );
					colors.push( color.g );
					colors.push( color.b );
					colors.push( color.r );
					colors.push( color.g );
					colors.push( color.b );
					colors.push( color.r );
					colors.push( color.g );
					colors.push( color.b );

				} );

			}

			bufferGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) );
			bufferGeometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );
			bufferGeometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );

			var material = new THREE.MeshPhongMaterial( {
				shininess: 80,
				vertexColors: THREE.VertexColors
			} );

			var mesh = new THREE.Mesh( bufferGeometry, material );
			scene.add( mesh );

		}

		function onWindowResize() {

			camera.aspect = window.innerWidth / window.innerHeight;
			camera.updateProjectionMatrix();
			renderer.setSize( window.innerWidth, window.innerHeight );

		}

		function animate( time ) {

			requestAnimationFrame( animate );

			controls.update();
			stats.update();
			renderer.render( scene, camera );

		}
		</script>
	</body>
</html>
